import './cms.carousel.scss';
import {iReactivityApi, RenderNode} from "../../packages/utils/types.base";
// @ts-ignore
import Swiper from '../../libs/swiper/swiper.esm.min';
import '../../libs/swiper/swiper-bundle.min.css';
import {createClasses} from "../../packages/utils/createClass";

/**
 * 创建CmsButton组件
 * @author  韦胜健
 * @date    2022/2/6 13:12
 */
export function createCmsCarousel({ type, designComponent, computed, useModel, onMounted, onBeforeUnmount, watch, provide, inject }: iReactivityApi) {

  const classes = createClasses(type);

  const Carousel = designComponent({
    props: {
      modelValue: { type: Number },
      childNum: { type: Number, required: true },
      autoplay: { type: Boolean },
      hideButton: { type: Boolean },
      loop: { type: Boolean },
    },
    slots: ['default'],
    emits: {
      onUpdateModelValue: (val?: number) => true,
    },
    setup({ props, slots, event: { emit } }: {
      props: {
        modelValue?: number,
        childNum: number,
        autoplay?: boolean,
        hideButton?: boolean,
        loop?: boolean,
      },
      event: {
        emit: { onUpdateModelValue: (val?: number) => void }
      },
      slots: {
        default: () => RenderNode,
      }
    }) {

      const model = useModel(() => props.modelValue, emit.onUpdateModelValue, {
        onChange: val => {
          swiper?.slideTo(val);
        }
      });

      const activeIndex = computed(() => model.value == null ? 0 : model.value);

      let el: HTMLDivElement | null = null;
      let swiper: any;

      const methods = {
        prev: () => swiper?.slidePrev(),
        next: () => swiper?.slideNext(),
        initialize: () => {
          swiper = new Swiper(el, {
            direction: 'horizontal',        // 垂直切换选项
            initialSlide: activeIndex.value,// 初始化的时候的索引
            loop: props.loop,               // 循环模式选项
            autoplay: props.autoplay ? {
              delay: 3000,
              stopOnLastSlide: false,
              disableOnInteraction: true,
            } : false,
            on: {
              slideChange(swiper: any) {
                let activeIndex = swiper.activeIndex;
                if (props.loop) {
                  activeIndex--;
                  if (activeIndex === -1) {
                    activeIndex = props.childNum - 1;
                  }
                  if (activeIndex === props.childNum) {
                    activeIndex = 0;
                  }
                  model.value = activeIndex;
                } else {
                  model.value = activeIndex;
                }
              },
            },
          });
        },
        destroy: () => {
          try {
            swiper?.destroy();
          } catch (e) {
            /*不知道为啥nuxt中这里会触发异常*/
            // console.error(e)
          }
        },
      };

      onMounted(() => {
        watch(() => props.childNum, () => {
          methods.destroy();
          methods.initialize();
        }, { immediate: true });
        watch(() => props.autoplay, () => {
          methods.destroy();
          methods.initialize();
        });
      });
      onBeforeUnmount(() => methods.destroy());

      provide('cms-carousel', { props });

      return () => (
        <div {...classes('swiper cms-carousel', { ref: (e: any) => el = e })}>
          <div {...classes('swiper-wrapper cms-carousel-wrapper')}>
            {slots.default()}
          </div>
          <div {...classes('cms-carousel-indicator')}>
            {new Array(props.childNum).fill(null).map((_, index) => (
              <div key={index} {...classes(`cms-carousel-indicator-item ${index === activeIndex.value ? 'cms-carousel-indicator-item-active' : ''}`)}/>
            ))}
          </div>
          {!props.hideButton && (
            <div {...classes('cms-carousel-operator')}>
              <button {...classes('cms-carousel-operator-button cms-carousel-operator-button-prev')} onClick={methods.prev}>
                <i {...classes('cms-icon plicon-left1')}/>
              </button>
              <button {...classes('cms-carousel-operator-button cms-carousel-operator-button-next')} onClick={methods.next}>
                <i {...classes('cms-icon plicon-right1')}/>
              </button>
            </div>
          )}
        </div>
      );
    },
  });

  const CarouselItem = designComponent({
    slots: ['default'],
    setup({ slots }: any) {

      const { props } = inject('cms-carousel') as any;

      return () => (
        <div  {...classes(`swiper-slide cms-carousel-item${props.hideButton ? '' : ' swiper-no-swiping'}`)} >
          {slots.default()}
        </div>
      );
    },
  });

  return {
    Carousel, CarouselItem,
  };
}
